/*
 * This file is part of the Try! Engine project.
 *
 * Copyright 2010-2011 Emanuele Bertoldi. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the modified BSD License along with this
 * program. If not, see <http://www.opensource.org/licenses/bsd-license.php>
 */

#include "toolmodellist.h"

using namespace Try;

ToolModelList::ToolModelList(QObject* parent)
    :   QAbstractListModel(parent)
{
    QHash<int,QByteArray> rolenames;
    rolenames[ToolModelList::NameRole] = "name";
    rolenames[ToolModelList::IconRole] = "icon";
    rolenames[ToolModelList::ActiveRole] = "active";
    this->setRoleNames(rolenames);
}

ToolModelList::~ToolModelList()
{
}

int ToolModelList::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent)

    return m_tools.count();
}

QVariant ToolModelList::data(const QModelIndex& index, int role) const
{
    if (index.isValid())
    {
        int row = index.row();
        Tool* tool = m_tools.at(row);

        switch (role)
        {
        case Qt::DisplayRole: // ToolModelList::NameRole
            return tool->name();

        case Qt::DecorationRole: // ToolModelList::IconRole
            return tool->icon();

        case ToolModelList::ActiveRole:
            return tool->isActive();

        default:
            break;
        }
    }

    return QVariant();
}

Tool* ToolModelList::toolAt(int row) const
{
    if (row < m_tools.count())
        return m_tools.at(row);

    return 0;
}

Tool* ToolModelList::activeTool() const
{
    foreach (Tool* tool, m_tools)
        if (tool->isActive())
            return tool;

    return 0;
}

bool ToolModelList::addTool(Tool* tool)
{
    return this->insertTool(m_tools.count(), tool);
}

bool ToolModelList::insertTool(int row, Tool* tool)
{
    if (tool && !m_tools.contains(tool))
    {
        if (row < 0)
            row = qMax(0, m_tools.count()-row);

        this->beginInsertRows(QModelIndex(), row, row+1);

        m_tools.insert(row, tool);

        QObject::connect(tool, SIGNAL(changed()), this, SLOT(onToolChanged()));
        QObject::connect(tool, SIGNAL(activationChanged()), this, SLOT(onToolActivationChanged()));

        this->endInsertRows();

        return true;
    }

    return false;
}

bool ToolModelList::removeTool(int row)
{
    if (row < 0)
        row = qMax(0, m_tools.count()-row);

    if (row < m_tools.count())
    {
        this->beginRemoveRows(QModelIndex(), row, row+1);

        Tool* tool = m_tools.takeAt(row);

        QObject::disconnect(tool, SIGNAL(changed()), this, SLOT(onToolChanged()));
        QObject::disconnect(tool, SIGNAL(activationChanged()), this, SLOT(onToolActivationChanged()));

        this->endRemoveRows();

        return true;
    }

    return false;
}

bool ToolModelList::removeTool(Tool* tool)
{
    if (m_tools.contains(tool))
    {
        int row = m_tools.indexOf(tool);

        return this->removeTool(row);
    }

    return false;
}

void ToolModelList::onToolChanged()
{
    Tool* tool = qobject_cast<Tool*>(this->sender());

    int id = 0;

    for (; id<this->rowCount(); ++id)
        if (this->toolAt(id) == tool)
            break;

    emit dataChanged(this->index(id), this->index(id));
    emit toolChanged(tool);
}

void ToolModelList::onToolActivationChanged()
{
    Tool* tool = qobject_cast<Tool*>(this->sender());

    int id = 0;

    for (; id<this->rowCount(); ++id)
        if (this->toolAt(id) == tool)
            break;

    emit dataChanged(this->index(id), this->index(id));
    emit toolActivationChanged(tool);
}
